<?php 
/**
 * Класс для работы с базой данных с библиотекой PDO
 * @author Бикмуллин Иван Олегович
 * @version 1.0
 */
class csvdb
{
 
    //переменные с именами хралинищ .csv
    var $messagesfile;
    var $commentsfile;
    
    /**
     * конструктор класса
     * @param string $messagesfile имя хралинища сообщений
     * @param string $commentsfile имя хранилища комментариев
     */
    function __construct($messagesfile, $commentsfile)
    {
        $this->messagesfile = $messagesfile;
        $this->commentsfile = $commentsfile;
        //создаем файлы если не существуют
        $handle = fopen($messagesfile,"a");fclose($handle);
        $handle = fopen($commentsfile,"a");fclose($handle);
    }
    /**
     * get_message
     * Функция для получения сообщения
     * @param string $tbl_name имя хранилища, из которого нужно достать сообщение
     * @param int $id уникальный идентификатор сообщения или комментария
     * @return array сообщение в виде массива
     */
    function get_message($tbl_name, $id)
    {
        if($handle = fopen($tbl_name.".csv", "r"))
        {
            $message = array();
            //шаблон для поиска сообщения по уникальному идентификатору
            $pattern = "/^".$id."/";
            //инициализация строки
            $out = "";
            //перебираем файл
            while($line = fgetcsv($handle))
            {
                //если найдено нужное сообщение
                if(preg_match($pattern, $line[0]))
                {
                    //записываем его в массив
                    $message['text'] = $line[1];
                    $message['message_date'] = $line[2];
                    //возвращаем полученное сообщение
                    return $message;
                }
            }
        }
    }
    /**
     * edit
     * Фукнция, обрабатывающая редактирование сообщения или комментария
     * @param string $tbl_name имя таблицы, в которой следует обновить полe text
     * @param string $text обновленный текст сообщения или комментария
     * @param int $id идентификатор сообщения или комментария
     */
    function edit($tbl_name, $id, $text)
    {
        $pattern = "/^".$id."/";
        //момент вызова функции
        $date = date("Y-m-d H:i:s");
        //файл c сообщениями
        $file = $tbl_name.".csv";
        //временный файл
        $file_tmp = "tmp_".$tbl_name.".csv";
        //проверяем, не было ли сбоя в предыдущем запуске скрипта
        if(file_exists($file_tmp)) die("fatal error!");
        //копируем содержимое файла в tmp
        if(copy($file, $file_tmp))
        {
            if($write=fopen($file,"w"))
            {
                //блокируем файл
                flock($write, LOCK_EX);
                $lines = file($file_tmp);
                //формируем массив значений для записи в .csv файл
                $list = array();
                //идентификатор редактируемого сообщения
                $list[0] = $id;
                //текст редактируемого сообщения
                $list[1] = $text;
                //дата редактируемого сообщения
                $list[2] = $date;
                if($file = "comments.csv")
                {
                    $arr = str_getcsv($lines[$id]);
                    $list[3] = $arr[3];
                }
               
                //записываем отредактированную строку
                if(!$lines[$id] = fputcsv($write, $list)) die ("Ошибка записи в файл");
                //открываем временный файл на чтение
                if(!$read = fopen($file_tmp, "r")) die("can't open file");
                //блокировка файла на чтение
                flock($read, LOCK_SH);
                //читаем построчно
                while($line = fgetcsv($read))
                {
                    //записываем построчно все кроме отредактированной строки, она уже записана в начале файла
                    if(!preg_match($pattern,$line[0]))
                    {
                        fputcsv($write, $line) or die('ошибка записи');
                    }
                }
                //снятие блокировок и закрытие файлов
                flock($read, LOCK_UN);
                fclose($read);
                flock($write, LOCK_UN);
                fclose($write);
                //удаление временного файла
                unlink($file_tmp);
                return true;
            }
        }
    }
    /**
     * add_message
     * Функция, обрабатывающая добавление сообщения в базу данных
     * @param string $text текст сообщения
     */
    function add_message($text)
    {
        //момент вызова функции
        $date = date("Y-m-d H:i:s");
        //файл c сообщениями
        $file = $this->messagesfile;
        //временный файл
        $file_tmp = "tmp_".$this->messagesfile;
        //проверяем, не было ли сбоя в предыдущем запуске скрипта
        if(file_exists($file_tmp)) die("fatal error!");
        //копируем содержимое файла в tmp
        if(copy($file, $file_tmp))
        {
            //если удачно скопировался, можно перезаписывать основной файл
            if($write=fopen($file, "w"))
            {
                //блокируем файл
                flock($write, LOCK_EX);
                //считаем количество строк в файле для определения поля id
                $lines = file($file_tmp);
                //получаем последний id в файле
                $lastid=count($lines);
                //инкрементируем последний id и получаем id для нового сообщения
                $id=$lastid++;
                //формируем массив значений для записи в .csv файл
                $list = array();
                //идентификатор
                $list[0] = $id;
                //текст сообщения
                $list[1] = $text;
                //дата и время записи сообщения
                $list[2] = $date;
                //записываем новую строку
                $result = fputcsv($write, $list) or die("Ошибка записи в файл");
                //открываем временный файл на чтение
                if(!$read = fopen($file_tmp, "r")) die("can't open file");
                //блокировка файла на чтение
                flock($read, LOCK_SH);
                //читаем построчно
                while($line = fgetcsv($read))
                {
                    //записываем построчно
                    fputcsv($write, $line) or die('ошибка записи');
                }
                //снятие блокировок и закрытие файлов
                flock($read, LOCK_UN);
                fclose($read);
                flock($write, LOCK_UN);
                fclose($write);
                //удаление временного файла
                unlink($file_tmp);
                return true;
            }
        }
    }
    function delete($tbl_name,$id)
    {
        //шаблон для поиска по идентификатору
        $pattern = "/^".$id."/";
        //добавление расширения к имени файла и запись готовой строки в переменную
        $file = $tbl_name.".csv";
        $file_tmp = "tmp_".$tbl_name.".csv";
        //в зависимости от имени файла -
        switch($tbl_name){
            //если имя файла comments.csv удаляем только комментарий
            case "comments":
                //если существует временный файл - выдать сообщения об ошибке
                if(file_exists($file_tmp)) die ("fatal error,temporary file already exists");
                //если удалось скопировать основной файл во временный
                if(copy($file, $file_tmp))
                {
                    //открываем на запись основной файл
                    if($write = fopen($file,"w"))
                    {
                        //блокировка основного файла на запись
                        flock($write, LOCK_EX);
                        //открываем временный файл на чтение
                        if(!$read = fopen($file_tmp, "r")) die("can't open temporary file");
                        //блокировка файла на чтение
                        flock($read, LOCK_SH);
                        //читаем построчно
                        while($line = fgetcsv($read))
                        {
                            //перезаписываем все комменатарии кроме того, который следует удалить
                            if(!preg_match($pattern, $line[0]))
                            {
                                fputcsv($write, $line) or die('ошибка записи');
                            }
                        }
                        //снятие блокировок и закрытие файлов
                        flock($read, LOCK_UN);
                        fclose($read);
                        flock($write, LOCK_UN);
                        fclose($write);
                        //удаление временного файла
                        unlink($file_tmp);
                    }
                }
                break;
                //если имя файла messages.csv удаляем само сообщение, и все комментарии к нему
            case "messages":
                //если существует временный файл выдать сообщение об ошибке
                if(file_exists($file_tmp)) die ("fatal error,temporary file already exists!");
                //если удалось скопировать основной файл во временный
                if(copy($file, $file_tmp))
                {
                    //открываем основной файл на запись
                    if($write = fopen($file,"w"))
                    {
                        //блокировка основного файла на зпись
                        flock($write, LOCK_EX);
                        //если не удается открыть временый файл выдать сообщение об ошибке
                        if(!$read = fopen($file_tmp, "r")) die("can't open temporary file");
                        //блокировка файла на чтение
                        flock($read, LOCK_SH);
                        //читаем построчно и записываем все кроме удаляемого сообщения
                        while($line = fgetcsv($read))
                        {
                            if(!preg_match($pattern, $line[0]))
                            {
                                fputcsv($write, $line) or die('Ошибка записи');
                            }

                        }
                        //снятие блокировок и закрытие файлов
                        flock($read, LOCK_UN);
                        fclose($read);
                        flock($write, LOCK_UN);
                        fclose($write);
                        //удаление временного файла
                        unlink($file_tmp);
                    }
                }
                //удаление всех комментариев к сообщению
                //если существует временный файл с комментариями - выдать сообщение об ошибке
                if(file_exists("tmp_".$this->commentsfile)) die("fatal error! temporary file already exists!");
                //если удалось скопировать основной файл во временный
                if(copy($this->commentsfile,"tmp_".$this->commentsfile))
                {
                    //открывает файл с комментариями на запись
                    if($write = fopen($this->commentsfile, "w"))
                    {
                        //блокировка файла на запись
                        flock($write, LOCK_EX);
                        //если не удается открыть временный файл -выдать сообщение об ошибке
                        if(!$read = fopen("tmp_".$this->commentsfile,"r")) die("can't open temporary file");
                        //блокировка файла на чтение
                        flock($read, LOCK_SH);
                        //читаем построчно и записываем все, кроме комментариев принадлежащих к удаляемому сообщению
                        while($line = fgetcsv($read))
                        {
                            if(!preg_match($pattern, $line[3]))
                            {
                                fputcsv($write, $line) or die('Ошибка запси');
                            }
                        }
                        //снятие блокировок и закрытие файлов
                        flock($read, LOCK_UN);
                        fclose($read);
                        flock($write, LOCK_UN);
                        fclose($write);
                        //удаление временного файла
                        unlink("tmp_".$this->commentsfile);
                    }
                }
                break;
        }
    }
    /**
     * add_comment
     * Функция, обрабатывающая добавления комментария к сообщению
     * @param string $text текст комментария
     * @param int $id идентификатор комментируемого сообщения
     */
    function add_comment($text,$id)
    {
        //шаблон для поиска сообщения, к котому нужно добавить комментарий
        $pattern = "/^".$id."/";
        //получение даты и времени момента вызова функции
        $date=date("Y-m-d H:i:s");
        //файл c сообщениями
        $file = $this->commentsfile;
        $lines = file($file);
        $lastid = count($lines);
        $uid = $lastid++;
        $list = array();
        //уникальный идентификатор
        $list[0] = $uid;
        //текст
        $list[1] = $text;
        //дата добавления комменатрия
        $list[2] = $date;
        //идентификатор комментируемого сообщения
        $list[3] = $id;
        $write=fopen($file,"a");
        if(!$result = fputcsv($write, $list)) die ("Ошибка записи в файл");
       

         
        //переписываем messages.csv, чтобы свежеоткомментированное сообщение было в топе
        //если существует временный файл с сообщениями выдать ошибку
        if(file_exists("tmp_".$this->messagesfile)) die("fatal error!");
        //копируем основной файл во временный
        if(copy($this->messagesfile, "tmp_".$this->messagesfile))
        {
            //открываем основной файл на запись
            if($write=fopen($this->messagesfile,"w"))
            {
                //блокировка файла на запись
                flock($write,LOCK_EX);
                //читаем в массив временный файл
                $lines = file("tmp_".$this->messagesfile);
                //инициализируем массив, в который запишем откомментированное сообщение
                $list = array();
                //цикл поиска нужного сообщения
                for($i=0;$i<=count($lines);$i++)
                {
                    $line = str_getcsv($lines[$i]);
                    if(preg_match($pattern, $line[0]))
                    {
                        //формируем массив значений для записи в .csv файл
                        $list[0] = $line[0];
                        $list[1] = $line[1];
                        $list[2] = $line[2];
                        break;
                    }
                }
                //записываем отредактированную строку или выдаем ошибку
                if(!$result = fputcsv($write, $list)) die ("Ошибка записи в файл");
                //открываем временный файл на чтение или выдаем ошибку
                if(!$read = fopen("tmp_".$this->messagesfile, "r")) die("can't open file");
                //блокировка файла на чтение
                flock($read, LOCK_SH);
                //читаем построчно
                while($line = fgetcsv($read))
                {
                    //записываем построчно кроме комментируемого сообщения, оно уже записано в начало файла
                    if(!preg_match($pattern,$line[0]))
                    {
                        fputcsv($write, $line) or die('ошибка записи');
                    }
                }
                //снятие блокировок и закрытие файлов
                flock($read, LOCK_UN);
                fclose($read);
                flock($write, LOCK_UN);
                fclose($write);
                //удаление временного файла
                unlink("tmp_".$this->messagesfile) or die("lox");
            }
        }
    }
    /**
     * get_messages
     * Функция, для получения всех сообщений 
     * return array
     */
    function get_messages()
    {
        $messages = array();
        //открываем файл с сообщениями
        $handle = fopen($this->messagesfile, "r+") or die("Can't open messages file");
        $lines = file($this->messagesfile);
        $rows = count($lines);
        if($rows = 0)
        {
            return false;
        }
        else 
        {
            while($line = fgetcsv($handle))
            {
                $messages[] = array("id"=>$line[0], "text"=>$line[1], "message_date"=>$line[2]);
            }
            //закрытие файла
            fclose($handle);
            
            return $messages;
        }
    }
    /**
     * get_comments
     * функция получения комментариев из базы с полученным id
     * @param int $id
     * @return array
     */
    function get_comments($id)
    {
        $comments = array();
        //открываем файл с комментариями
        $handle = fopen($this->commentsfile, "r+") or die("can't open comments.csv");
        //инициалицируем строку для вывода тела страницы
        $out = "";
        //шаблон для поиска комментариев к сообщению c данным id
        $pattern = "/^".$id."/";
        //цикл чтения из файла и вывода в строку комментариев
        $lines = file($this->commentsfile);
        //перебираем файл
        while($line = fgetcsv($handle))
        {
            //поиск нужных комментариев
            if (preg_match($pattern, $line[3]))
            {
                //$str = str_getcsv($lines[$i]);
                $comments[] = array("id"=>$line[0], "text"=>$line[1], "comment_date"=>$line[2]);
            }
        }
            //закрытие файла
        fclose($handle);
        //возвращаем ассоциативный массив
        return $comments;
    }
}
?>